package sv.gob.mh.dgii.common;

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.springframework.ui.Model;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;

public class GenericValidator<T> {

    private String targetVariableName;
    private T target;
    private static ValidatorFactory validatorFactory;

    public GenericValidator() {
    }

    public GenericValidator(String targetVariableName, T taget) {
        this.targetVariableName = targetVariableName;
        this.target = taget;
    }

    public GenericValidator(String targetVariableFormName, String targetVariableName, T taget) {
        this.targetVariableName = targetVariableName;
        this.target = taget;
    }

    public BindingResult validate(Model model) {
        Validator validator = getValidatorFactory().getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(target);
        BindingResult result = new BeanPropertyBindingResult(target, targetVariableName);
        for (ConstraintViolation<T> constraint : constraintViolations) {
            result.rejectValue(constraint.getPropertyPath().toString(), null, constraint.getMessage());
        }
        String attribName = BindingResult.MODEL_KEY_PREFIX + targetVariableName;
        model.addAttribute(attribName, result);
        return result;
    }

    public static ValidatorFactory getValidatorFactory() {
        if (validatorFactory == null) {
            validatorFactory = Validation.buildDefaultValidatorFactory();
        }
        return validatorFactory;
    }

    /**
     * @return the targetVariableName
     */
    public String getTargetVariableName() {
        return targetVariableName;
    }

    /**
     * @param targetVariableName the targetVariableName to set
     */
    public void setTargetVariableName(String targetVariableName) {
        this.targetVariableName = targetVariableName;
    }

    /**
     * @return the target
     */
    public T getTarget() {
        return target;
    }

    /**
     * @param target the target to set
     */
    public void setTarget(T target) {
        this.target = target;
    }
}
